#! /bin/sh
# PCP QA Test No. 040
# mem leak in pmlogger
#
# Copyright (c) 1995-2002 Silicon Graphics, Inc.  All Rights Reserved.
#

seq=`basename $0`
echo "QA output created by $seq"

# get standard filters
. ./common.product
. ./common.filter
. ./common.check

trap "$sudo rm -f $tmp.*; exit" 0 1 2 3 15

if ps l -p 1 2>/dev/null | sed -e 1q | grep RSS >/dev/null
then
    ps_arg=l
elif ps -l -p 1 2>/dev/null | sed -e 1q | grep RSS >/dev/null
then
    ps_arg=-l
elif ps -o uid,pid,rss,fname -p 1 2>/dev/null | sed -e 1q | grep RSS >/dev/null
then
    ps_arg="-o uid,pid,rss,fname"
else
    echo "$seq: how do I coerce RSS from your ps?"
fi

rss_field=`ps $ps_arg -p 1 2>/dev/null | $PCP_AWK_PROG '
NR == 1	{ for (i = 1; i <= NF; i++) {
	    if ($i == "RSS") {
		print i
		break
	    }
	  }
	  exit
	}'`
pid_field=`ps $ps_arg -p 1 2>/dev/null | $PCP_AWK_PROG '
NR == 1	{ for (i = 1; i <= NF; i++) {
	    if ($i == "PID") {
		print i
		break
	    }
	  }
	  exit
	}'`
echo "rss_field=$rss_field pid_field=$pid_field" >>$seq_full
ps $ps_arg -p 1 >>$seq_full

_fail()
{
    echo "Arrgh: $1"
    echo "Error: pmlogger virtual or resident size grew ... memory leak?"
    echo "       or maybe pmlogger died, or failed to start"
    echo "       my pmlogger pid=$mylogger"
    echo
    echo "ps output ..."
    cat $tmp.ps
    echo
    echo "pmlogger log ..."
    cat $tmp.log
}

# and NO malloc() hardening ...
#
case $PCP_PLATFORM
in
    openbsd)
    	unset MALLOC_OPTIONS
	;;
esac

# real QA test starts here

cat <<End-of-File >$tmp.config
log mandatory on 20 msec {
    pmcd.control
}
End-of-File

#debug# _start_up_pmlogger -c $tmp.config -Daf,appl2,desperate -l $tmp.log -s 1000 $tmp
_start_up_pmlogger -c $tmp.config -l $tmp.log -s 1000 $tmp
mylogger=$pid
_wait_for_pmlogger $mylogger $tmp.log || _exit 1

seen=0
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
do
sleep 1
ps $ps_arg -p $mylogger \
    | $PCP_AWK_PROG '
NR == 1			{ print; next }
$'$pid_field' == '$mylogger'	{ print }'
done \
| sed -e '/RSS/d' \
| tee $tmp.ps \
| $PCP_AWK_PROG '{ print $'$rss_field' }' >$tmp.tmp

# expect ...
# - 15 ps observations
# - max < 1.05* min
# - no monotonic increase
#
obs="`wc -l <$tmp.tmp | sed -e 's/ //g'`"
if [ "$obs" -ne 15 ]
then
    _fail "insufficient results ($obs not 15)"
fi
min="`LC_COLLATE=POSIX sort -n <$tmp.tmp | head -1`"
max="`LC_COLLATE=POSIX sort -nr <$tmp.tmp | head -1`"
echo "min rss $min, max rss $max" >>$seq_full
if [ "`expr $max \* 100`" -ge "`expr $min \* 105`" ]
then
    _fail "rss max ($max) more than 1.05 times rss min ($min)"
fi
rm -f $tmp.bad
( cat $tmp.tmp; echo 0 ) | $PCP_AWK_PROG '
BEGIN	{ last = 0 }
NR > 1	{ if ($1 > last) {
	    inc++
	  }
	  else {
	    if (inc > 1) print "[" NR-1 "] " inc " increasing values" >>"'$tmp.bad'"
	  }
	}
	{ last = $1 }'
if [ -s $tmp.bad ]
then
    _fail "rss increasing ...\
`cat $tmp.bad`"
fi

# pmlogger should run for about 20 seconds, and we've spent about
# 15 seconds in the loop above, so allow pmlogger to get close to
# being done before calling _wait_pmlogger_end (otherwise
# _wait_pmlogger_end can lose patience before pmlogger exits)
#
sleep 5

_wait_pmlogger_end $mylogger || _exit 1
cat $tmp.log >>$seq_full
echo
echo "pmlogger log"
_filter_pmlogger_log <$tmp.log

echo "pmResults in archive ... `pmdumplog $tmp | grep '^[0-2]' | wc -l | sed -e 's/ //g'`" >>$seq_full

exit 0
